package com.opensource.component.register;

import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;

import com.opensource.component.annotation.StatementMapping;
import com.opensource.component.demo.DeclareReportStatementRequest;
import com.opensource.component.ift.StatementController;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import lombok.SneakyThrows;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author ZonLen since on 2022/5/30 下午8:58
 */
@Component
public class RegisterStatementBeanPostProcessor implements BeanPostProcessor, EnvironmentAware {

  private static String CONTEXT_PATH;
  private static String APP_NAME;

  @SneakyThrows
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    //注册
    if (bean instanceof StatementController) {
      StatementController<?, ?> statementController = (StatementController<?, ?>) bean;
      final Class<?> aClass = statementController.getClass();
      final Method method = aClass.getDeclaredMethod(StatementController.fetchDataMethodName,
          DeclareReportStatementRequest.class);
      final String code = statementController.code();
      final RequestMapping requestMapping = findMergedAnnotation(method, RequestMapping.class);
      if (null == requestMapping) {
        throw new RuntimeException("xxx");
      }
      final String[] path = requestMapping.value();
      final Map<String, String> convertDeclare = new HashMap<>();
      for (Field field : method.getReturnType().getDeclaredFields()) {
        final StatementMapping statementMapping = field.getAnnotation(StatementMapping.class);
        if (statementMapping == null) {
          continue;
        }
        convertDeclare.put(field.getName(), statementMapping.mappingName());
      }
      RegisterStatementManager.init(
          new RegisterInterfaceStatement(code, "http://" + APP_NAME + CONTEXT_PATH + path[0],
              convertDeclare));
    }
    return bean;
  }

  @Override
  public void setEnvironment(Environment environment) {
    CONTEXT_PATH = environment.getProperty("server.servlet.context-path", "");
    APP_NAME = environment.getProperty("spring.application.name", "");
  }
}
